<?php
/*
 * @Author: XIAOSHU<itree@itreeon.com>
 * @Date: 2025-05-07
 * @Description: 数据分析页面控制器
 */

namespace App\Http\Controllers\Analysis;

use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Illuminate\Support\Facades\DB;

/**
 * @package App\Http\Controllers\Analysis
 */
class PageController
{
    public function get(): StreamedResponse
    {
        // 设置 SSE 响应头
        $headers = [
            'Content-Type' => 'text/event-stream',
            'Cache-Control' => 'no-cache',
            'Connection' => 'keep-alive',
            'X-Accel-Buffering' => 'no', // 禁用 Nginx 缓冲
            // 添加跨域支持
            'Access-Control-Allow-Origin' => '*',
            'Access-Control-Allow-Methods' => 'GET, OPTIONS',
            'Access-Control-Allow-Credentials' => 'true',
            'Access-Control-Allow-Headers' => 'Content-Type, X-Requested-With'
        ];

        $date = request()->get('date');

        $res = response()->stream(
            function () use ($date) {

                $dates = $this->getRange($date);

                // 保持连接开放
                while (true) {
                    // 生成数据（示例：当前时间）
                    $data = [
                        'time' => date('Y-m-d H:i:s'),
                        'message' => '您好,极光纺织可视化平台',
                        'params' => $dates,
                        'data' => [
                            // 数据统计
                            'dept' => $this->getDeptNum($dates),
                            // 日来货入库数据
                            'dailyReceive' => $this->getDailyStorageData($dates),
                            // 'dailyReceiveRadar' => $this->getDailyStorageRadarData($dates),
                            // 日生产数
                            'departmentProduction' => $this->getDepartmentProductionData($dates),
                            // 月销量走势图数据
                            'monthlySales' => $this->getMonthlySalesData(),
                            // 日发货走势图数据
                            'daySales' => $this->getDailyShipmentData($dates),
                            
                            // 白/夜班产量
                            'twoShiftProduction' => $this->getTwoShiftProductionData($dates),

                            // 接单产品排行榜
                            'productRank' => $this->getProductRankData($dates),

                            // 日打样数
                            'dailySample' => $this->getDailySampleData($dates),

                            // 检验/倒卷
                            'checkData' => $this->getCheckData($dates),
                        ]
                    ];

                    // 按 SSE 格式发送数据
                    echo "event: message\n";  // 事件类型（可选）
                    echo "data: " . json_encode($data) . "\n\n";

                    // 刷新输出缓冲区
                    ob_flush();
                    flush();

                    // 检查连接是否中断
                    if (connection_aborted()) {
                        break;
                    }

                    // 等待 10 秒后继续
                    sleep(20);
                }
            },
            200,
            $headers
        );
        
        return $res;
    }
    

    /**
     * 获取日期范围
     * @param string|array $date
     * @return array
     */
    protected function getRange($date): array
    {
        if (is_array($date)) {
            return $date;
        } else if (is_string($date)) {
            $end = date('Y-m-d'); // 默认结束日期为今天
            
            if ($date == 'today' || $date == '今天') {
                $start = date('Y-m-d'); // 开始日期也是今天
            } else if ($date == 'yesterday' || $date == '昨天') {
                $start = date('Y-m-d', strtotime('-1 day'));
            } else if ($date == 'week' || $date == '近一周') {
                $start = date('Y-m-d', strtotime('-7 days'));
            } else if ($date == 'month' || $date == '近一月') {
                $start = date('Y-m-d', strtotime('-30 days'));
            } else {
                // 默认返回最近30天
                $start = date('Y-m-d', strtotime('-7 days'));
            }
            
            return [$start, $end];
        }

        // 如果没有指定日期或格式不正确，默认返回最近一周
        $end = date('Y-m-d');
        $start = date('Y-m-d', strtotime('-7 days'));
        
        return [$start, $end];
    }

    /**
     * 获取每日客户来货入库数据
     */
    protected function getDeptNum($dates){
        $res = [];
        // 来货数
        $receive = DB::table('sys_customer_receive_details')
                ->whereBetween('created_at', $dates)
                ->value(DB::raw('SUM(quantity) as total_quantity')) ?? 0;
        
        // 发货数
        $shipment = DB::table('sys_market_delivery_details')
                ->whereBetween('created_at', $dates)
                ->value(DB::raw('SUM(quantity) as total_quantity')) ?? 0;

        // 退仓数
        $return = DB::table('sys_market_backwarehouse_details')
                ->whereBetween('created_at', $dates)
                ->value(DB::raw('SUM(quantity) as total_quantity')) ?? 0;

        // 倒卷数
        $rollback = DB::table('sys_open_card_details')
                ->whereBetween('created_at', $dates)
                ->value(DB::raw('SUM(roll_quantity) as total_quantity')) ?? 0;

        // 生产数
        $production = DB::table('sys_pro_process_pass')
                ->whereBetween('created_at', $dates)
                ->whereIn('process_id', [5, 17])
                ->value(DB::raw('SUM(out_quantity) as total_quantity')) ?? 0;

        // 检验数
        $check = DB::table('sys_pro_processes_inspect_pack')
                ->whereBetween('created_at', $dates)
                ->value(DB::raw('SUM(quantity) as total_quantity')) ?? 0;

        // 格式化数字并构建返回数组
        return [
            '来货数:' . number_format($receive, 0, '.', ','),
            '发货数:' . number_format($shipment, 0, '.', ','),
            '退仓数:' . number_format($return, 0, '.', ','),
            '倒卷数:' . number_format($rollback, 0, '.', ','),
            '生产数:' . number_format($production, 0, '.', ','),
            '检验数:' . number_format($check, 0, '.', ',')
        ];
    }

    /**
     * 获取每日客户来货入库数据
     * @return array
     */
    protected function getDailyStorageData($dates)
    {
            $data = DB::table('sys_customer_receive_details')
                ->whereBetween('created_at', $dates)
                ->select(
                    DB::raw('DATE(created_at) as date'),
                    DB::raw('COUNT(DISTINCT customer_id) as customer_count'),
                    DB::raw('SUM(quantity) as total_quantity')
                )
                ->groupBy('date')
                ->orderBy('date')
                ->get()
                ->toArray();
                
            return [
                'xAxis' => array_map(function ($d) {
                    return substr($d, 5);
                }, array_column($data, 'date')) ,
                'series' => [
                    [
                        'name' => '来货数',
                        'color' => ['#48cefd', '#5356f1'],
                        'data' => array_column($data, 'total_quantity')
                    ],
                    [
                        'name' => '客户数',
                        'color' => ['#9e70ff', '#6e5eff'],
                        'data' => array_column($data, 'customer_count')
                    ]
                ]
            ];
    }

    /**
     * 获取每日客户来货入库的布图数据
     */
    protected function getDailyStorageRadarData($dates)
    {
        // 获取客户来货产品
        $data = DB::table('sys_customer_receive_details')
            ->join('basedata_material', 'basedata_material.id', '=', 'sys_customer_receive_details.material_id')
            ->whereBetween('sys_customer_receive_details.created_at', $dates)
            ->select(
                DB::raw('COUNT(DISTINCT sys_customer_receive_details.material_id) as material_count'),
                DB::raw('SUM(sys_customer_receive_details.quantity) as total_quantity')
            )
            ->groupBy('sys_customer_receive_details.material_id')
            ->orderBy('total_quantity', 'desc')
            ->limit(6)
            ->get();
        
        // 准备雷达图数据
        $categories = [];
        $quantities = [];
        $customerCounts = [];
        
        foreach ($data as $item) {
            $categories[] = ['text' => $item->category ?? '未分类'];
            $quantities[] = $item->total_quantity;
            $customerCounts[] = $item->customer_count;
        }
        
        // 如果分类不足6个，补充空分类
        while (count($categories) < 6) {
            $categories[] = ['text' => '分类' . (count($categories) + 1)];
            $quantities[] = 0;
            $customerCounts[] = 0;
        }
        
        return [
            'title' => '产品分布',
            'position' => ['center', '85%'],
            'center' => ['50%', '50%'],
            'indicator' => $categories,
            'data' => [
                [
                    'name' => '数量',
                    'color' => '#0DF5F8',
                    'value' => $quantities,
                ],
                [
                    'name' => '产品',
                    'color' => '#7921AD',
                    'value' => $customerCounts,
                ]
            ]
        ];
    }
    
    /**
     * 获取部门生产走势图数据
     * @return array
     */
    protected function getDepartmentProductionData($dates)
    {
        $data = DB::table('sys_pro_process_pass')
            ->join('basedata_pro_dept', 'basedata_pro_dept.id', 'sys_pro_process_pass.pro_dept_id')
            ->whereBetween('sys_pro_process_pass.created_at', $dates)
            ->whereIn('sys_pro_process_pass.process_id', [5, 17])
            ->select(
                DB::raw('DATE(sys_pro_process_pass.created_at) as date'),
                'basedata_pro_dept.name as department',
                DB::raw('SUM(sys_pro_process_pass.out_quantity) as total_quantity')
            )
            ->groupBy('date', 'department')
            ->orderBy('date')
            ->get();
                
        // 处理数据，按部门分组
        $dates = [];
        $departments = [];
        $seriesData = [];
        
        foreach ($data as $record) {
            if (!in_array($record->date, $dates)) {
                $dates[] = $record->date;
            }
            
            if (!in_array($record->department, $departments)) {
                $departments[] = $record->department;
                $seriesData[$record->department] = [];
            }
            
            $seriesData[$record->department][$record->date] = $record->total_quantity;
        }
        
        // 构建系列数据
        $series = [];
        foreach ($departments as $department) {
            $departmentData = [];
            foreach ($dates as $date) {
                $departmentData[] = $seriesData[$department][$date] ?? 0;
            }
            
            $series[] = [
                'name' => $department,
                'type' => 'line',
                'data' => $departmentData
            ];
        }
        
        return [
            'xAxis' => array_map(function ($d) {
                return substr($d, 5);
            }, $dates),
            'series' => $series
        ];
    }
    
    /**
     * 获取月销量走势图数据
     * @return array
     */
    protected function getMonthlySalesData()
    {
            $data = DB::table('sys_market_delivery_details')
                ->where("code", "like", "L%")
                ->where('billdate', '>=', date('Y-m-d', strtotime('-12 months')))
                ->whereNull('deletor_id')
                ->select(
                    DB::raw('YEAR(billdate) as year'),
                    DB::raw('MONTH(billdate) as month'),
                    // DB::raw('SUM(amount) as total_amount'),
                    DB::raw('count(*) as total'),
                    DB::raw('SUM(quantity) as total_quantity')
                )
                ->groupBy('year', 'month')
                ->orderBy('year')
                ->orderBy('month')
                ->get();
                
            $months = [];
            // $amounts = [];
            $cnts = [];
            $quantities = [];
            
            foreach ($data as $record) {
                $monthKey = $record->year . '-' . str_pad($record->month, 2, '0', STR_PAD_LEFT);
                $months[] = $monthKey;
            // $amounts[] = $record->total_amount;
            $cnts[] = $record->total;
            $quantities[] = $record->total_quantity;
            }
            
            return [
                'xAxis' => array_map(function ($d) {
                    return substr($d, 5);
                }, $months),
                'series' => [
                // [
                //     'name' => '销售金额',
                //     'data' => $amounts
                // ],
                    [
                        'name' => '销售单数',
                        'data' => $cnts
                    ],
                    [
                        'name' => '销售数量',
                        'data' => $quantities
                    ]
                ]
            ];
    }
    
    /**
     * 获取日发货走势图数据
     * @return array
     */
    protected function getDailyShipmentData($dates)
    {
        $data = DB::table('sys_market_delivery_details')
            ->where("code", "like", "L%")
            ->whereBetween('billdate', $dates)
            ->whereNull('deletor_id')
            ->select(
                DB::raw('DATE(billdate) as date'),
                DB::raw('COUNT(*) as shipment_count'),
                DB::raw('SUM(quantity) as total_quantity')
            )
            ->groupBy('date')
            ->orderBy('date')
            ->get();
            
        $dates = [];
        $counts = [];
        $quantities = [];
        
        foreach ($data as $record) {
            $dates[] = $record->date;
            $counts[] = $record->shipment_count;
            $quantities[] = $record->total_quantity;
        }

        return [
            'xAxis' => array_map(function ($d) {
                return substr($d, 5);
            }, $dates),
            'series' => [
                [
                    'name' => '发货单数',
                    'color' => ['#48cefd', '#5356f1'],
                    'data' => $counts
                ],
                [
                    'name' => '发货数量',
                    'color' => ['#9e70ff', '#6e5eff'],
                    'data' => $quantities
                ]
            ]
        ];
    }
    
    /**
     * 获取白/夜班产量
     * @return array
     */
    protected function getTwoShiftProductionData($dates)
    {
        // 白班数据（6:00-18:00）
        $dayShiftData = DB::table('sys_pro_process_pass')
            ->whereBetween('created_at', $dates)
            ->whereRaw('HOUR(created_at) >= 6 AND HOUR(created_at) < 18')
            ->whereIn('process_id', [5, 17])
            ->select(
                DB::raw('DATE(created_at) as date'),
                DB::raw('SUM(out_quantity) as total_quantity')
            )
            ->groupBy('date')
            ->orderBy('date')
            ->get();
            
        // 夜班数据（18:00-次日6:00）
        $nightShiftData = DB::table('sys_pro_process_pass')
            ->whereBetween('created_at', $dates)
            ->whereRaw('HOUR(created_at) < 6 OR HOUR(created_at) >= 18')
            ->whereIn('process_id', [5, 17])
            ->select(
                DB::raw('DATE(IF(HOUR(created_at) < 6, DATE_SUB(created_at, INTERVAL 1 DAY), created_at)) as shift_date'),
                DB::raw('SUM(out_quantity) as total_quantity')
            )
            ->groupBy('shift_date')
            ->orderBy('shift_date')
            ->get();
            
        // 准备数据
        $datelist = [];
        $dayQuantities = [];
        $nightQuantities = [];
        
        foreach ($dayShiftData as $record) {
            $datelist[] = $record->date;
            $dayQuantities[] = $record->total_quantity;
            // 查找夜班的数据
            $nightRecord = $nightShiftData->firstWhere('shift_date', $record->date);
            $nightQuantities[] = $nightRecord ? $nightRecord->total_quantity : 0;
        }
        
        return [
            'xAxis' => array_map(function ($d) {
                return substr($d, 5);
            }, $datelist),
            'series' => [
                [
                    'name' => '白班产量',
                    'color' => ['#48cefd', '#5356f1'],
                    'data' => $dayQuantities
                ],
                [
                    'name' => '夜班产量',
                    'color' => ['#9e70ff', '#6e5eff'],
                    'data' => $nightQuantities
                ]
            ]
        ];
    }

    /**
     * 客户下单产品排行榜
     * @return array
     */
    protected function getProductRankData($dates){
        // 获取客户来货产品排行榜数据（前10名）
        $data = DB::table('sys_customer_receive_details')
            ->whereBetween('created_at', $dates)
            ->select(
                'craft_remark',
                DB::raw('COUNT(*) as customer_count'), // 订单数
                DB::raw('SUM(quantity) as total_quantity') // 米数
            )
            ->groupBy('craft_remark')
            ->orderBy('total_quantity', 'desc')
            ->limit(10)
            ->get();
            
        $names = [];
        $quantity = [];
        $order_count = [];
        
        foreach ($data as $item) {
            $names[] = $item->craft_remark;
            $quantity[] = $item->total_quantity;
            $order_count[] = $item->customer_count;
        }

        return [
            'xAxis' => $names,
            'series' => [
                // [
                //     'name' => '单数',
                //     'color' => ['#48cefd', '#5356f1'],
                //     'data' => $order_count
                // ],
                [],
                [
                    'name' => '数量',
                    'color' => ['#9e70ff', '#6e5eff'],
                    'data' => $quantity
                ]
            ]
        ];
    }

    /**
     * 日打样数据
     * 获取 接样/生产/发货 数量
     * @return array
     */
    protected function getDailySampleData($dates){
        // 接样数据
        $receiveData = DB::table('sys_customer_receive_details')
            ->whereBetween('created_at', $dates)
            ->where('is_sample', 1)
            ->select(
                DB::raw('DATE(created_at) as date'),
                DB::raw('count(*) as total_quantity')
            )
            ->groupBy('date')
            ->orderBy('date')
            ->get();
            
        // 生产数据
        $productionData = DB::table('sys_pro_process_pass')
            ->leftJoin('sys_open_card_details', 'sys_open_card_details.id', 'sys_pro_process_pass.open_card_id')
            ->where('sys_open_card_details.is_sample', 1)
            ->whereBetween('sys_pro_process_pass.created_at', $dates)
            ->whereIn('sys_pro_process_pass.process_id', [5, 17])
            ->select(
                DB::raw('DATE(sys_pro_process_pass.created_at) as date'),
                DB::raw('count(DISTINCT sys_pro_process_pass.open_card_id) as total_quantity')
            )
            ->groupBy('date')
            ->orderBy('date')
            ->get();
            
        // 发货数据
        $shipmentData = DB::table('sys_market_delivery_details')
            ->whereBetween('created_at', $dates)
            ->where('sample_data', '小样')
            ->select(
                DB::raw('DATE(created_at) as date'),
                DB::raw('count(*) as total_quantity')
            )
            ->groupBy('date')
            ->orderBy('date')
            ->get();
            
        // 准备数据
        $dateslist = [];
        $receiveCounts = [];
        $productionCounts = [];
        $shipmentCounts = [];
        
        foreach ($receiveData as $data) {
            $dateslist[] = $data->date;
            $receiveCounts[] = $data->total_quantity;

            // 查找生产的数据
            $ppRecord = $productionData->firstWhere('date', $data->date);
            $productionCounts[] = $ppRecord ? $ppRecord->total_quantity : 0;

            // 查找发货的数据
            $ssRecord = $shipmentData->firstWhere('date', $data->date);
            $shipmentCounts[] = $ssRecord ? $ssRecord->total_quantity : 0;
        }
        
        return [
            'xAxis' => array_map(function ($d) {
                return substr($d, 5);
            }, $dateslist),
            'series' => [
                [
                    'name' => '接样数',
                    'color' => ['#48cefd', '#5356f1'],
                    'data' => $receiveCounts
                ],
                [
                    'name' => '生产数',
                    'color' => ['#9e70ff', '#6e5eff'],
                    'data' => $productionCounts
                ],
                [
                    'name' => '发货数',
                    'color' => ['#ffa600', '#ff7c43'],
                    'data' => $shipmentCounts
                ]
            ]
        ];
    }

    /**
     * 获取检验和推荐数据
     * @return array
     */
    protected function getCheckData($dates)
    {
        // 获取检验员检验数据
        $inspectData = DB::table('sys_pro_processes_inspect_pack')
            ->join('basedata_employee', 'basedata_employee.id', 'sys_pro_processes_inspect_pack.swipor_id')
            ->whereBetween('sys_pro_processes_inspect_pack.created_at', $dates)
            ->select(
                'basedata_employee.name as user_name',
                DB::raw('SUM(sys_pro_processes_inspect_pack.quantity) as total_quantity')
            )
            ->groupBy('basedata_employee.id', 'basedata_employee.name')
            ->orderBy('total_quantity', 'desc')
            ->limit(10)
            ->get();

        // 生产数据
        $recommendData = DB::table('sys_pro_process_pass')
            ->join('basedata_employee', 'basedata_employee.id', 'sys_pro_process_pass.swipor_id')
            ->whereBetween('sys_pro_process_pass.created_at', $dates)
            ->whereIn('sys_pro_process_pass.process_id', [5,17])
            ->select(
                'basedata_employee.name as user_name',
                DB::raw('SUM(sys_pro_process_pass.out_quantity) as total_quantity')
            )
            ->groupBy('basedata_employee.id', 'basedata_employee.name')
            ->orderBy('total_quantity', 'desc')
            ->limit(10)
            ->get();

        // 准备返回数据
        $inspectNames = [];
        $inspectQuantities = [];
        $recommendNames = [];
        $recommendCounts = [];

        foreach ($inspectData as $item) {
            $inspectNames[] = $item->user_name;
            $inspectQuantities[] = $item->total_quantity;
        }

        foreach ($recommendData as $item) {
            $recommendNames[] = $item->user_name;
            $recommendCounts[] = $item->total_quantity;
        }

        return [
            'inspect' => [
                'xAxis' => $inspectNames,
                'series' => [
                    [
                        'name' => '检验数量',
                        'data' => $inspectQuantities
                    ]
                ]
            ],
            'recommend' => [
                'xAxis' => $recommendNames,
                'series' => [
                    [
                        'name' => '生产数量',
                        'data' => $recommendCounts
                    ]
                ]
            ]
        ];
    }
}